import { Vec3 } from "./Vec3";
import { ArrayType, EPSILON } from "./common"
/**
 * 二维向量类
 * @class
 * @author jsbrml
 */
class Vec2 extends ArrayType {
    /**
     * 构造函数。
     * @constructor
     */
    constructor(element = [0, 0]) {
        super(element);
    }
    /**
     * @property  {Number} x 
     * 【读写】获取向量的x分量。
     */
    get x() {
        return this[0];
    }
    set x(v) {
        this[0] = v;
    }
    /**
     * @property  {Number} y 
     * 【读写】获取向量的y分量。
     */
    get y() {
        return this[1];
    }
    set y(v) {
        this[1] = v;
    }
    /**
     * 向量对象转化为字符串。
     * @method
     */
    toString() {
        return `Vec2(${this.join(',')})`
    }
    /**
     * 向量拷贝。
     * @method
     */
    copy(v) {
        this[0] = v[0];
        this[1] = v[1];
        return this;
    }
    /**
     * 当前向量和目标向量是否相等。
     * @method
     */
    equal(v) {
        return (Math.abs(this[0] - v[0]) <= EPSILON) && (Math.abs(this[1] - v[1]) <= EPSILON);
    }
    /**
     * 向量克隆。
     * @method
     */
    clone() {
        return new Vec2(this);
    }
    /**
     * 向量加法。
     * @method
     */
    add(v) {
        this[0] += v[0];
        this[1] += v[1];
        return this;
    }
    /**
     * 向量减法。
     * @method
     */
    sub(v) {
        this[0] -= v[0];
        this[1] -= v[1];
        return this;
    }
    /**
     * 向量乘法。
     * @method
     */
    multiply(v) {
        this[0] *= v[0];
        this[1] *= v[1];
        return this;
    }
    /**
     * 向量除法。
     * @method
     */
    div(v) {
        this[0] /= v[0];
        this[1] /= v[1];
        return this;
    }
    /**
     * 向量缩放。
     * @method
     */
    scale(v) {
        this[0] *= v;
        this[1] *= v;
        return this;
    }
    /**
     * 向量反向。
     * @method
     */
    negate() {
        this[0] *= -1;
        this[1] *= -1;
        return this;
    }
    /**
     * 计算向量长度。
     * @method
     */
    length() {
        return Math.sqrt(this[0] * this[0] + this[1] * this[1]);
    }
    /**
     * 计算向量长度。
     * @method
     */
    distance(v) {
        let x = this[0] - v[0], y = this[1] - v[1];
        return Math.sqrt(x*x+ y*y);
    }
    /**
     * 向量插值。
     * @param {Number} t 插值参数，0表示起点 1表示终点
     * @method
     */
    lerp(t) {
        this[0] *= t;
        this[1] *= t;
        return this;
    }
    /**
     * 向量旋转。
     * @param {Number} rad 旋转角度。单位:弧度。
     * @method
     */
    rotate(rad) {
        let p0 = this[0],
            p1 = this[1],
            sinC = Math.sin(rad),
            cosC = Math.cos(rad);
        this[0] = p0 * cosC - p1 * sinC;
        this[1] = p0 * sinC + p1 * cosC;
        return this;
    }
    /**
     * 计算当前向量到目标向量的夹角。
     * @param {Vec2} v 目标向量。
     * @method
     */
    angle(v = [1, 0]) {
        const x1 = this[0];
        const y1 = this[1];
        const x2 = v[0];
        const y2 = v[1];
        const mag = Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2);
        const cosine = mag && (x1 * x2 + y1 * y2) / mag;
        return Math.acos(Math.min(Math.max(cosine, -1), 1));
    }
    /**
     * 向量的逆。
     * @method
     */
    inverse() {
        this[0] = 1.0 / this[0];
        this[1] = 1.0 / this[1];
        return this;
    }
    /**
     * 向量的绝对值变换。
     * @method
     */
    abs() {
        this[0] = Math.abs(this[0]);
        this[1] = Math.abs(this[1]);
        return this;
    }
    /**
     * 当前向量和目标向量的点积。
     * @param {Vec2} v 目标向量。
     * @method
     */
    dot(v) {
        return this[0] * v[0] + this[1] * v[1];
    }
    /**
     * 当前向量和目标向量的叉集。
     * @param {Vec2} v 目标向量。
     * @method
     * @reture {Vec3} 返回一个三维向量。
     */
    cross(v) {
        let out = new Vec3();
        const z = this[0] * v[1] - this[1] * v[0];
        out[0] = out[1] = 0;
        out[2] = z;
        return out;
    }
    /**
     * 乘2阶矩阵
     * @method
     */
    transformMat2(m) {
        var x = this[0],
            y = this[1];
        this[0] = m[0] * x + m[2] * y;
        this[1] = m[1] * x + m[3] * y;
        return this;
    }
    /**
     * 乘3阶矩阵
     * @method
     */
    transformMat3(m) {
        var x = this[0],
            y = this[1];
        this[0] = m[0] * x + m[3] * y + m[6];
        this[1] = m[1] * x + m[4] * y + m[7];
        return this;
    }
    /**
     * 乘4阶矩阵
     * @method
     */
    transformMat4(m) {
        let x = this[0];
        let y = this[1];
        this[0] = m[0] * x + m[4] * y + m[12];
        this[1] = m[1] * x + m[5] * y + m[13];
        return this;
    }
    /**
     * 向量归一化。
     * @method
     */
    normalize() {
        const x = this[0];
        const y = this[1];
        let len = x * x + y * y;
        if (len > 0) {
            //TODO: evaluate use of glm_invsqrt here?
            len = 1 / Math.sqrt(len);
        }
        this[0] *= len;
        this[1] *= len;
        return this;
    }
}
export { Vec2 }